home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1122 / 1122.xpi / chrome / tabmixplus.jar / content / tabmixplus / click / click.js
Text File  |  2009-09-27  |  38KB  |  975 lines

  1. var onDoubleClick = false;
  2.  
  3. // single click function
  4. //
  5. function TM_checkClick (event) {
  6.   if (!event)
  7.     return;
  8.   if (event.button == 2)
  9.     return; // right click
  10.   if (event.button == 0 && event.detail > 1)
  11.     return; // double click (with left button)
  12.  
  13.   var target = event.originalTarget;
  14.   // don't do anything if user left click on close tab button , or on any other button on tab or tabbar
  15.   if (event.button == 0 && (target.getAttribute("anonid") == "tmp-close-button" ||
  16.       target.localName == "toolbarbutton"))
  17.      return;
  18.  
  19.   // only allow middle-click on close tab button on tab to go throw as middle-click on the tab
  20.   if (event.button == 1 && target.localName == "toolbarbutton" && target.getAttribute("anonid") != "tmp-close-button")
  21.      return;
  22.  
  23.   onDoubleClick = false;
  24.  
  25.   var aTab = target;
  26.   while ( aTab.localName != "tabs" ) {
  27.     if ( aTab.localName == "tab" )
  28.       break;
  29.     if ( aTab.parentNode )
  30.       aTab = aTab.parentNode;
  31.     else
  32.       return;
  33.   }
  34.  
  35.   var clickOutTabs = aTab.localName == "tabs";
  36.   // for tab flip
  37.   if ( !clickOutTabs && event.button == 0 && aTab.hasAttribute("clickOnCurrent") ) {
  38.     aTab.removeAttribute("clickOnCurrent");
  39.     var tabFlip = TMP_getBoolPref(tabxBranch, "tabFlip", false);
  40.     var tabFlipDelay = TMP_getIntPref (tabxBranch, "tabFlipDelay", 250);
  41.     if (tabFlip && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey){
  42.       window.setTimeout(function () {
  43.                 if (!onDoubleClick) {
  44.                     gBrowser.previousTab(aTab);
  45.                     gBrowser.stopMouseHoverSelect(aTab);
  46.                     content.focus();
  47.                 }
  48.       }, tabFlipDelay );
  49.       return;
  50.     }
  51.   }
  52.  
  53.   var prefName
  54.   /* middle click*/
  55.   if (event.button == 1)
  56.     prefName = "middle"
  57.   /* shift click*/
  58.   else if (event.button == 0 && event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey)
  59.     prefName = "shift"
  60.   /* alt click*/
  61.   else if (event.button == 0 && event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey)
  62.     prefName = "alt"
  63.   /* ctrl click*/
  64.   else if (event.button == 0 && (event.ctrlKey && !event.metaKey || !event.ctrlKey && event.metaKey) && !event.shiftKey && !event.altKey)
  65.     prefName = "ctrl"
  66.  
  67.   TMclickAction(prefName, clickOutTabs, aTab);
  68.   event.stopPropagation();
  69. }
  70.  
  71. // Double click function
  72. //
  73. function TM_onTabBarDblClick (e) {
  74.   if ( !e || e.button != 0 || e.ctrlKey || e.shiftKey || e.altKey || e.metaKey )
  75.     return;
  76.   onDoubleClick = true;
  77.   var aTab = e.originalTarget;
  78.  
  79.   // don't do anything if user click on close tab button , or on any other button on tab or tabbar
  80.   if (aTab.getAttribute("anonid") == "tmp-close-button" ||
  81.       aTab.localName == "toolbarbutton")
  82.      return;
  83.  
  84.   while ( aTab.localName != "tabs" ) {
  85.     if ( aTab.localName == "tab" )
  86.       break;
  87.     aTab = aTab.parentNode;
  88.   }
  89.  
  90.   TMclickAction( "dbl", aTab.localName == "tabs", aTab );
  91. }
  92.  
  93. // call action function from click on tabs or tabbar
  94. //
  95. function TMclickAction ( pref, clickOutTabs, aTab ) {
  96.   if (!pref) return; // just in case we missed something
  97.  
  98.   var defaultPref = {middleClickTab:2, middleClickTabbar:10, shiftClickTab:5, shiftClickTabbar:0,
  99.                      altClickTab:6, altClickTabbar:0, ctrlClickTab:22, ctrlClickTabbar:0,
  100.                      dblClickTab:0, dblClickTabbar:1};
  101.  
  102.   pref += clickOutTabs ? "ClickTabbar" : "ClickTab";
  103.   var action = TMP_getIntPref (tabxBranch, pref , defaultPref[pref]);
  104.  
  105.   content.focus();
  106.  
  107.   switch ( action ) {
  108.     case 0 :
  109.       break;
  110.     case 1 :
  111.       BrowserOpenTab();
  112.       break;
  113.     case 2 :
  114.       // removeTab tab after delay,
  115.       // if the tab is in the middle of selecting or we just add new tab
  116.       // it can caused problem
  117.       function _delayCloseTab(b, tab){
  118.          b.closeTab(tab);
  119.       }
  120.       if (aTab.localName != "tab")
  121.          aTab = gBrowser.mCurrentTab;
  122.       setTimeout(_delayCloseTab, 0, gBrowser, aTab);
  123.       break;
  124.     case 3 :
  125.       gBrowser.duplicateTab(aTab);
  126.       break;
  127.     case 4 :
  128.       gBrowser.reloadTab(aTab);
  129.       break;
  130.     case 5 :
  131.       gBrowser.protectTab(aTab);
  132.       break;
  133.     case 6 :
  134.       gBrowser.lockTab(aTab);
  135.       break;
  136.     case 7 :
  137.       gBrowser.reloadAllTabs(aTab);
  138.       break;
  139.     case 8:
  140.       gBrowser.removeAllTabsBut(aTab);
  141.       break;
  142.     case 9:
  143.       gBrowser.closeAllTabs();
  144.       break;
  145.     case 10:
  146.       TMP_ClosedTabs.undoCloseTab();
  147.       break;
  148.     case 11:
  149.       gBrowser.renameTab(aTab);
  150.       break;
  151.     case 12: //taken from tco
  152.       if (SessionSaver && SessionSaver.snapBackTab)
  153.         SessionSaver.snapBackTab(SessionSaver.snapback_noFX, SessionSaver.snapback_willFocus);
  154.       break;
  155.     case 13:
  156.       TMP_ClosedTabs.restoreTab("original", -2);
  157.       break;
  158.     case 14:
  159.       gBrowser.duplicateInWindow(aTab, false);
  160.       break;
  161.     case 15:
  162.       gBrowser.freezeTab(aTab);
  163.       break;
  164.     case 16:
  165.       gBrowser.reloadAllTabsBut(aTab);
  166.       break;
  167.     case 17:
  168.       if (window.getComputedStyle(gBrowser, null).direction == "ltr")
  169.         gBrowser.closeLeftTabs(aTab);
  170.       else
  171.         gBrowser.closeRightTabs(aTab);
  172.       break;
  173.     case 18:
  174.       if (window.getComputedStyle(gBrowser, null).direction == "ltr")
  175.         gBrowser.closeRightTabs(aTab);
  176.       else
  177.         gBrowser.closeLeftTabs(aTab);
  178.       break;
  179.     case 19:
  180.       if (window.getComputedStyle(gBrowser, null).direction == "ltr")
  181.         gBrowser.reloadLeftTabs(aTab);
  182.       else
  183.         gBrowser.reloadRightTabs(aTab);
  184.       break;
  185.     case 20:
  186.       if (window.getComputedStyle(gBrowser, null).direction == "ltr")
  187.         gBrowser.reloadRightTabs(aTab);
  188.       else
  189.         gBrowser.reloadLeftTabs(aTab);
  190.       break;
  191.     case 21: // taken from tco
  192.       if (aTab.localName != "tab")
  193.           aTab = gBrowser.mCurrentTab;
  194.       var href;
  195.       if (window.IeView && window.IeView.ieViewLaunch) {
  196.         href = gBrowser.getBrowserForTab(aTab).currentURI.spec;
  197.         IeView.ieViewLaunch("Internet Explorer.lnk", href);
  198.       }
  199.       else if (window.gIeTab && window.gIeTab.switchTabEngine) {
  200.         if (gBrowser.selectedTab != aTab)
  201.           gBrowser.selectedTab = aTab;
  202.         gIeTab.switchTabEngine(aTab, gIeTab.getBoolPref("ietab.alwaysNewTab", false));
  203.       }
  204.       else if(window.ieview && window.ieview.launch) {
  205.         href = gBrowser.getBrowserForTab(aTab).currentURI.spec;
  206.         ieview.launch(href);
  207.       }
  208.       break;
  209.     case 22:
  210.       gBrowser.SelectToMerge(aTab);
  211.       break;
  212.     case 23:
  213.       dtMergeWindows.mergeWindows();
  214.       break;
  215.     case 24:
  216.       gBrowser.closeGroupTabs(aTab);
  217.       break;
  218.     case 25:
  219.         if (aTab.localName != "tab")
  220.           aTab = gBrowser.mCurrentTab;
  221.         PlacesCommandHook.bookmarkPage(aTab.linkedBrowser, PlacesUtils.bookmarksMenuFolderId, true);
  222.         break;
  223.     case 26:
  224.         PlacesCommandHook.bookmarkCurrentPages();
  225.         break;
  226.     case 27:
  227.       gBrowser.duplicateInWindow(aTab, true);
  228.       break;
  229.     case 28:
  230.       gBrowser.copyTabUrl(aTab);
  231.       break;
  232.     case 29:
  233.       var event = document.createEvent("Events");
  234.       event.initEvent("click", true, true);
  235.       middleMousePaste(event);
  236.       break;
  237.     case 30: // enable/disable AutoReload
  238.       if (aTab.autoReloadEnabled == null)
  239.         setupAutoReload(aTab);
  240.       gBrowser.onAutoReloadEnable(aTab);
  241.   }
  242. }
  243.  
  244. function Tm_checkTabClick(event) {
  245.    var tabContextMenu = gBrowser.tabContextMenu;
  246.    // Undo close tab Commands - firefox 3.0 toggle this menu item also when submneu are show
  247.    var undoClose = tabxPrefs.getBoolPref("undoClose");
  248.    TMP_showItem("context_undoCloseTab", tabxPrefs.getBoolPref("undoCloseTabMenu") && undoClose);
  249.  
  250.    if (event.originalTarget != tabContextMenu)
  251.      return true;
  252.  
  253.    var item;
  254.    if (document.popupNode.parentNode)
  255.       item = document.popupNode.parentNode.parentNode.id;
  256.    if (item && (item == "btn_tabslist" || item == "btn_tabslistSorted"))
  257.       gBrowser.mContextTab = document.popupNode.tab;
  258.  
  259.    var clickOutTabs = document.popupNode.localName == "tabs";
  260.    var aTab = clickOutTabs ? gBrowser.mCurrentTab : gBrowser.mContextTab;
  261.  
  262.    var cIndex = aTab._tPos;
  263.    var isOneWindow = numberOfWindows() == 1;
  264.  
  265.    var newTab = document.getElementById("context_newTab");
  266.    TMP_showItem(newTab, tabxPrefs.getBoolPref("newTabMenu"));
  267.    if (clickOutTabs) {
  268.       TMP_setItem(newTab, "label", newTab.getAttribute("_newtab"));
  269.       TMP_setItem(newTab, "oncommand", "TMP_BrowserOpenTab();");
  270.    }
  271.    else {
  272.       TMP_setItem(newTab, "label", newTab.getAttribute("_newtab") + "  " + newTab.getAttribute("_afterthis"));
  273.       TMP_setItem(newTab, "oncommand", "var tabbrowser = this.parentNode.parentNode.parentNode.parentNode; TMP_BrowserOpenTab(tabbrowser.mContextTab);");
  274.    }
  275.  
  276.    // Duplicate Commands
  277.    TMP_showItem("tm-duplicateTab", tabxPrefs.getBoolPref("duplicateMenu"));
  278.    TMP_showItem("tm-duplicateinWin", tabxPrefs.getBoolPref("duplicateinWinMenu") && !gSingleWindowMode);
  279.    TMP_showItem("tm-detachTab", tabxPrefs.getBoolPref("detachTabMenu") && !gSingleWindowMode);
  280.  
  281.    TMP_showItem("tm-mergeWindowsTab", tabxPrefs.getBoolPref("showMergeWindow") && (!gSingleWindowMode || (gSingleWindowMode && !isOneWindow)));
  282.    var showRenameTabMenu = tabxPrefs.getBoolPref("renameTabMenu");
  283.    TMP_showItem("tm-renameTab", showRenameTabMenu);
  284.    TMP_showItem("tm-copyTabUrl", tabxPrefs.getBoolPref("copyTabUrlMenu"));
  285.  
  286.    //  ---------------- menuseparator ---------------- //
  287.  
  288.    // Reload Commands
  289.    TMP_showItem("context_reloadTab", tabxPrefs.getBoolPref("reloadTabMenu"));
  290.    TMP_showItem("context_reloadAllTabs", tabxPrefs.getBoolPref("reloadAllMenu"));
  291.    TMP_showItem("tm-autoreloadTab_menu", tabxPrefs.getBoolPref("autoReloadMenu"));
  292.    TMP_showItem("tm-reloadRight", tabxPrefs.getBoolPref("reloadRightMenu"));
  293.    TMP_showItem("tm-reloadLeft", tabxPrefs.getBoolPref("reloadLeftMenu"));
  294.    TMP_showItem("tm-reloadOther", tabxPrefs.getBoolPref("reloadOtherMenu"));
  295.  
  296.    //  ---------------- menuseparator ---------------- //
  297.  
  298.    TMP_showItem("tm-undoCloseList", tabxPrefs.getBoolPref("undoCloseListMenu") && undoClose);
  299.  
  300.    //  ---------------- menuseparator ---------------- //
  301.  
  302.    // Close tab Commands
  303.    TMP_showItem("context_closeTab", tabxPrefs.getBoolPref("closeTabMenu"));
  304.    TMP_showItem("tm-closeAllTabs", tabxPrefs.getBoolPref("closeAllMenu"));
  305.    TMP_showItem("tm-closeSimilar", tabxPrefs.getBoolPref("closeSimilarTabs"));
  306.    TMP_showItem("context_closeOtherTabs", tabxPrefs.getBoolPref("closeOtherMenu"));
  307.    TMP_showItem("tm-closeLeftTabs", tabxPrefs.getBoolPref("closeLeftMenu"));
  308.    TMP_showItem("tm-closeRightTabs", tabxPrefs.getBoolPref("closeRightMenu"));
  309.  
  310.    //  ---------------- menuseparator ---------------- //
  311.  
  312.    TMP_showItem("tm-docShell", tabxPrefs.getBoolPref("docShellMenu"));
  313.    TMP_showItem("tm-freezeTab", tabxPrefs.getBoolPref("freezeTabMenu"));
  314.    TMP_showItem("tm-protectTab", tabxPrefs.getBoolPref("protectTabMenu"));
  315.    TMP_showItem("tm-lockTab", tabxPrefs.getBoolPref("lockTabMenu"));
  316.  
  317.    //  ---------------- menuseparator ---------------- //
  318.  
  319.    TMP_showItem("context_bookmarkTab", tabxPrefs.getBoolPref("bookmarkTabMenu"));
  320.    TMP_showItem("context_bookmarkAllTabs", tabxPrefs.getBoolPref("bookmarkTabsMenu"));
  321.  
  322.    // we call this again by popupshown to make sure we don't show 2 menuseparator together
  323.    TMP_tabContextMenuShown(event);
  324.  
  325.    if (showRenameTabMenu) {
  326.       // disabled rename if the title not ready yet
  327.       var titleNotReady;
  328.       if (aTab.hasAttribute("busy")) {
  329.          var browser = gBrowser.getBrowserForTab(aTab);
  330.          var url = browser.contentDocument.baseURI || browser.currentURI.spec;
  331.          var docTitle = getTitleFromBookmark(url, browser.contentDocument.title, aTab.getAttribute("tabmix_bookmarkId"));
  332.          if (!docTitle || docTitle == gBrowser.mStringBundle.getString("tabs.untitled"))
  333.             titleNotReady = true;
  334.       }
  335.       TMP_setItem("tm-renameTab", "disabled", titleNotReady);
  336.    }
  337.  
  338.    var protectedTab = aTab.hasAttribute("protected");
  339.    var lockedTab = aTab.hasAttribute("locked");
  340.    var tabsCount = gBrowser.mTabContainer.childNodes.length;
  341.  
  342.    // In Firefox version prior to 3.5 gBrowser.removeTab don't remove the last tab when the tab bar is hidded
  343.    var keepLastTab = tabsCount == 1 && tabxPrefs.getBoolPref("keepLastTab");
  344.    var tabBarCollapsed = tabsCount == 1 && gTabmixPrefs.getBoolPref("browser.tabs.autoHide") && !gIsFirefox35;
  345.    TMP_setItem("context_closeTab", "disabled", protectedTab || keepLastTab || tabBarCollapsed);
  346.    TMP_setItem("tm-closeAllTabs", "disabled", keepLastTab || tabBarCollapsed);
  347.    TMP_setItem("context_closeOtherTabs", "disabled", tabsCount == 1);
  348.  
  349.    var closeTabsEmpty = TMP_ClosedTabs.count < 1;
  350.    TMP_setItem("context_undoCloseTab", "disabled", closeTabsEmpty);
  351.    TMP_setItem("tm-undoCloseList", "disabled", closeTabsEmpty);
  352.  
  353.    TMP_setItem("tm-mergeWindowsTab", "disabled", isOneWindow);
  354.  
  355.    TMP_setItem("tm-closeRightTabs", "disabled", cIndex == tabsCount - 1);
  356.    TMP_setItem("tm-closeLeftTabs", "disabled", cIndex == 0);
  357.    TMP_setItem("tm-reloadRight", "disabled", cIndex == tabsCount - 1);
  358.    TMP_setItem("tm-reloadLeft", "disabled", cIndex == 0);
  359.    TMP_setItem("tm-reloadOther", "disabled", tabsCount == 1);
  360.  
  361.    TMP_setItem("tm-docShell", "disabled", clickOutTabs);
  362.  
  363.    var freezeTabMenu = document.getElementById("tm-freezeTab");
  364.    if ( !freezeTabMenu.hidden )
  365.       TMP_setItem(freezeTabMenu, "checked", lockedTab && protectedTab);
  366.  
  367.    var lockTabMenu = document.getElementById("tm-lockTab");
  368.    if ( !lockTabMenu.hidden )
  369.       TMP_setItem(lockTabMenu, "checked", lockedTab);
  370.  
  371.    var protectTabMenu = document.getElementById("tm-protectTab");
  372.    if ( !protectTabMenu.hidden )
  373.       TMP_setItem(protectTabMenu, "checked", protectedTab);
  374.  
  375.    return true;
  376. }
  377.  
  378. // don't show 2 menuseparator together
  379. // this function is call by "popupshown" event
  380. // this is only to the case that other extensions popupshowing run after our Tm_checkTabClick
  381. function TMP_tabContextMenuShown(event) {
  382.    var tabContextMenu = gBrowser.tabContextMenu;
  383.    if (event.originalTarget != tabContextMenu)
  384.      return;
  385.    // don't show 2 menuseparator together
  386.    var hideNextSeparator = true, lastVisible, hideMenu = true;
  387.    for(var mi = tabContextMenu.firstChild; mi; mi = mi.nextSibling) {
  388.       if (mi.localName == "menuseparator") {
  389.          mi.hidden = hideNextSeparator;
  390.          if (!hideNextSeparator) {
  391.             hideNextSeparator = true;
  392.             lastVisible = mi;
  393.          }
  394.       }
  395.       else if(!mi.hidden && !mi.collapsed) {
  396.          hideNextSeparator = false;
  397.          hideMenu = false;
  398.       }
  399.    }
  400.  
  401.    // hide the last visible menuseparator if it is the last visible in the menu
  402.    if (hideNextSeparator && lastVisible)
  403.       lastVisible.hidden = true;
  404.  
  405.    // if all the menu are hidden don't show the popup
  406.    if (hideMenu)
  407.       tabContextMenu.hidePopup();
  408. }
  409.  
  410. function TM_checkContentMenu (event) {
  411.   if (!gContextMenu || event.originalTarget != document.getElementById("contentAreaContextMenu"))
  412.     return true;
  413.  
  414.   try {
  415.     var showFreezeTab = gTabmixPrefs.getBoolPref("extensions.tabmix.freezeTabContent");
  416.     var showLockTab = gTabmixPrefs.getBoolPref("extensions.tabmix.lockTabContent");
  417.     var showProtectTab = gTabmixPrefs.getBoolPref("extensions.tabmix.protectTabContent");
  418.     var showTabsList = gTabmixPrefs.getBoolPref("extensions.tabmix.tabsList");
  419.     var showCloseTab = gTabmixPrefs.getBoolPref("extensions.tabmix.closeTabContent");
  420.     var showUndoCloseTab = gTabmixPrefs.getBoolPref("extensions.tabmix.undoCloseTabContent");
  421.     var showUndoCloseList = gTabmixPrefs.getBoolPref("extensions.tabmix.undoCloseListContent");
  422.     var undoClose = gTabmixPrefs.getBoolPref("extensions.tabmix.undoClose");
  423.     var showDuplicateTab = gTabmixPrefs.getBoolPref("extensions.tabmix.duplicateTabContent");
  424.     var showDuplicateWin = gTabmixPrefs.getBoolPref("extensions.tabmix.duplicateWinContent");
  425.     var showDetachTab = gTabmixPrefs.getBoolPref("extensions.tabmix.detachTabContent");
  426.     var showLinkWithHist = gTabmixPrefs.getBoolPref("extensions.tabmix.linkWithHistory");
  427.     var showMerge = gTabmixPrefs.getBoolPref("extensions.tabmix.mergeWindowContent");
  428.     var showOpenHere = gTabmixPrefs.getBoolPref("extensions.tabmix.openLinkHere");
  429.     var showInverseLink = gTabmixPrefs.getBoolPref("extensions.tabmix.openInverseLink");
  430.     var showAutoReload = gTabmixPrefs.getBoolPref("extensions.tabmix.autoReloadContent");
  431.     var bgPref = gTabmixPrefs.getBoolPref("browser.tabs.loadInBackground");
  432.     var isOneWindow = numberOfWindows() == 1;
  433.  
  434.   var tabsListMenu = document.getElementById("tm-tabsList");
  435.   var closeTabMenu = document.getElementById("tm-content-closetab");
  436.   var freezeTabMenu = document.getElementById("tm-content-freezeTab");
  437.   var lockTabMenu = document.getElementById("tm-content-lockTab");
  438.   var protectTabMenu = document.getElementById("tm-content-protectTab");
  439.   var undoCloseTabMenu = document.getElementById("tm-content-undoCloseTab");
  440.   var undoCloseListMenu = document.getElementById("tm-content-undoCloseList");
  441.   var undoCloseSep = document.getElementById("tm-content-undoCloseSep");
  442.   var duplicateTabMenu = document.getElementById("tm-duplicateTabContext");
  443.   var duplicateWinMenu = document.getElementById("tm-duplicateinWinContext");
  444.   var detachTabMenu = document.getElementById("tm-detachTabContext");
  445.   var linkWithHist = document.getElementById("tm-linkWithhistory");
  446.   var mergeMenu = document.getElementById("tm-mergeWindows");
  447.   var miscSep = document.getElementById("tm-content-miscSep");
  448.   var textSep = document.getElementById("tm-content-textSep");
  449.   var openHere = document.getElementById("tm-openlinkhere");
  450.   var inverseLink = document.getElementById("tm-openinverselink");
  451.   var autoReload = document.getElementById("tm-autoreload_menu");
  452.  
  453.   var contentClick = gContextMenu.onTextInput || gContextMenu.onLink || gContextMenu.onImage;
  454.   var tabsCount = gBrowser.mTabContainer.childNodes.length;
  455.   var closeTabsEmpty = TMP_ClosedTabs.count < 1;
  456.   var protectedTab = gBrowser.mCurrentTab.hasAttribute("protected");
  457.   var lockedTab = gBrowser.mCurrentTab.hasAttribute("locked");
  458.  
  459.   // from Firefox 3.7 2009-09-11 there is gContextMenu.openLinkInCurrent
  460.   // Firefox only show this menu when the selection text is url see Bug 454518
  461.   // we cahck if gContextMenu.linkURL contain URL
  462.   // 
  463.   // we can remove this menu in tabmix.js but it is safer to just hide it each time
  464.   if (gIsFirefox37) {
  465.     // the label for this menu is "Open Link" 
  466.     // we use our own menu "Open Link in This Tab"
  467.     document.getElementById("context-openlinkincurrent").hidden = true;
  468.   }
  469.   openHere.hidden = (!gContextMenu.onLink && !gContextMenu.linkURL) || !showOpenHere;
  470.   inverseLink.hidden = !gContextMenu.onLink || !showInverseLink;
  471.   if (!inverseLink.hidden){
  472.     var focusType = bgPref ? "fg":"bg";
  473.     inverseLink.setAttribute("label", inverseLink.getAttribute(focusType+"label"));
  474.     inverseLink.setAttribute("accesskey", inverseLink.getAttribute(focusType+"accesskey"));
  475.   }
  476.   linkWithHist.hidden = !gContextMenu.onLink || !showLinkWithHist;
  477.   closeTabMenu.hidden = !showCloseTab || contentClick;
  478.   var keepLastTab = tabsCount == 1 && tabxPrefs.getBoolPref("keepLastTab");
  479.   var tabBarCollapsed = tabsCount == 1 && gTabmixPrefs.getBoolPref("browser.tabs.autoHide") && !gIsFirefox35;
  480.   closeTabMenu.setAttribute("disabled", protectedTab || keepLastTab || tabBarCollapsed);
  481.   freezeTabMenu.hidden = !showFreezeTab || contentClick;
  482.   lockTabMenu.hidden = !showLockTab || contentClick;
  483.   lockTabMenu.setAttribute("checked", lockedTab);
  484.   protectTabMenu.hidden = !showProtectTab || contentClick;
  485.   protectTabMenu.setAttribute("checked", protectedTab);
  486.   duplicateTabMenu.hidden = !showDuplicateTab || contentClick;
  487.   detachTabMenu.hidden = !showDetachTab || contentClick || gSingleWindowMode;
  488.   duplicateWinMenu.hidden = !showDuplicateWin || contentClick || gSingleWindowMode;
  489.   freezeTabMenu.setAttribute("checked", protectedTab && lockedTab);
  490.   tabsListMenu.hidden = !showTabsList || contentClick;
  491.   undoCloseTabMenu.hidden = closeTabsEmpty || !showUndoCloseTab || !undoClose || contentClick || gContextMenu.isTextSelected;
  492.   undoCloseListMenu.hidden = closeTabsEmpty || !showUndoCloseList || !undoClose || contentClick || gContextMenu.isTextSelected;
  493.   undoCloseSep.hidden = undoCloseTabMenu.hidden && undoCloseListMenu.hidden || gContextMenu.isTextSelected && closeTabMenu.hidden && lockTabMenu.hidden && protectTabMenu.hidden && tabsListMenu.hidden  && freezeTabMenu.hidden;
  494.   mergeMenu.hidden = !showMerge || isOneWindow || contentClick;
  495.   miscSep.hidden = mergeMenu.hidden && closeTabMenu.hidden && duplicateTabMenu.hidden && duplicateWinMenu.hidden && lockTabMenu.hidden && protectTabMenu.hidden && tabsListMenu.hidden  && freezeTabMenu.hidden || gContextMenu.isTextSelected;
  496.   textSep.hidden = !gContextMenu.isTextSelected || mergeMenu.hidden && duplicateTabMenu.hidden && duplicateWinMenu.hidden && closeTabMenu.hidden && lockTabMenu.hidden && protectTabMenu.hidden && tabsListMenu.hidden  && freezeTabMenu.hidden && undoCloseTabMenu.hidden && undoCloseListMenu.hidden;
  497.   autoReload.hidden = !showAutoReload || contentClick || gContextMenu.isTextSelected;
  498.  
  499.   var hideOpenAllLinks = gTabmixPrefs.getBoolPref("extensions.tabmix.openAllLinks") ?
  500.                   TMP_openMultipleLinks(true) : true;
  501.   document.getElementById("tm-openAllLinks").hidden = hideOpenAllLinks;
  502.   return true;
  503.  
  504.   } catch (ex) {TMP_ASSERT(ex);}  
  505. }
  506.  
  507. function onAutoReloadPopupShowing(aPopup) {
  508.   function setLabel(aItem, aTime) {
  509.     var seconds = aTime;
  510.     var timeLabel = aItem.getAttribute("_label") + " ";
  511.     if (seconds > 59) {
  512.       var minutes = parseInt(aTime / 60);
  513.       timeLabel += minutes + " " + (minutes > 1 ? customMenu.getAttribute("minutes") : customMenu.getAttribute("minute"));
  514.       seconds -= 60*minutes;
  515.       if (seconds)
  516.         timeLabel += " ";
  517.     }
  518.     if (seconds || !timeLabel)
  519.       timeLabel += seconds + " " + customMenu.getAttribute("seconds");
  520.     aItem.setAttribute("label", timeLabel);
  521.   }
  522.   var menuItems = aPopup.childNodes;
  523.  
  524.   var node = document.popupNode;
  525.   aPopup._tab = node && node.localName == "tab" ? node : gBrowser.mCurrentTab;
  526.   if (aPopup._tab.autoReloadEnabled == null)
  527.     setupAutoReload(aPopup._tab);
  528.  
  529.   var customReloadTime = tabxPrefs.getIntPref("custom_reload_time");
  530.   var customMenu = menuItems[3];
  531.   customMenu.setAttribute("value", customReloadTime);
  532.   setLabel(customMenu, customReloadTime);
  533.  
  534.   menuItems[0].setAttribute("checked", aPopup._tab.autoReloadEnabled);
  535.   setLabel(menuItems[0], aPopup._tab.autoReloadTime);
  536.  
  537.   var checked = aPopup.getElementsByAttribute("value" , aPopup._tab.autoReloadTime);
  538.   if (checked.length)
  539.     checked[checked.length - 1].setAttribute("checked", "true");
  540. }
  541.  
  542. function TMP_openMultipleLinks(check) {
  543.    var focusedWindow = document.commandDispatcher.focusedWindow;
  544.    if (focusedWindow == window)
  545.       focusedWindow = _content;
  546.  
  547.    var nsISelectionObject = focusedWindow.getSelection();
  548.    if (nsISelectionObject.isCollapsed) // nothing selected
  549.      return true;
  550.  
  551.    var myNodeFilter = {
  552.       acceptNode : function(n) {
  553.          if(n.nodeName == 'A' || n.nodeName == 'li') {
  554.             return NodeFilter.FILTER_ACCEPT;
  555.          }
  556.          else {
  557.             return NodeFilter.FILTER_SKIP;
  558.          }
  559.       }
  560.    };
  561.  
  562.    // do urlSecurityCheck for each link in the treeWalker....
  563.    var _document = focusedWindow.document.documentElement.ownerDocument;
  564.    const nsIScriptSecurityManager = Components.interfaces.nsIScriptSecurityManager;
  565.    var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
  566.                           .getService(nsIScriptSecurityManager);
  567.    var flags = nsIScriptSecurityManager.STANDARD;
  568.    function links_urlSecurityCheck(url) {
  569.      if (!url)
  570.         return false;
  571.  
  572.      if (!_document) // just in case....
  573.         return true;
  574.  
  575.      try {
  576.         secMan.checkLoadURIStrWithPrincipal(_document.nodePrincipal, url, flags);
  577.      } catch (e) {
  578.         return false;
  579.      }
  580.        return true;
  581.    }
  582.  
  583.    var range = nsISelectionObject.getRangeAt(0);
  584.    var treeWalker = window._content.document.createTreeWalker(
  585.          range.cloneContents(),
  586.          NodeFilter.SHOW_ELEMENT,
  587.          myNodeFilter,
  588.          true);
  589.    var nextEpisode = treeWalker.nextNode();
  590.    var newTab, firstTab, url;
  591.    while (nextEpisode != null) {
  592.       url = (nextEpisode.nodeName == "li") ? nextEpisode.firstChild.href : nextEpisode.href;
  593.       if (links_urlSecurityCheck(url)) {
  594.          if (check)
  595.             return false;
  596.          newTab = gBrowser.addTab(url);
  597.          if (!firstTab) {
  598.             firstTab = newTab;
  599.             gBrowser.TMP_selectNewForegroundTab(firstTab, null, url);
  600.          }
  601.       }
  602.       nextEpisode = treeWalker.nextNode();
  603.    }
  604.    return true;
  605. }
  606.  
  607. function checkForCtrlClick(aEvent) {
  608.   var aButton = aEvent.target;
  609.   if (!aButton.disabled && aEvent.button == 0 && (aEvent.ctrlKey || aEvent.metaKey)) {
  610.     if (aButton.id == "btn_undoclose")
  611.       TMP_ClosedTabs.undoCloseTab();
  612.     else
  613.       BrowserCloseTabOrWindow();
  614.  
  615.     aButton.setAttribute("afterctrlclick", true);
  616.   }
  617. }
  618.  
  619. function isAfterCtrlClick(aButton) {
  620.   if (aButton.getAttribute("afterctrlclick")) {
  621.     aButton.removeAttribute("afterctrlclick");
  622.     if (aButton.hasAttribute("open"))
  623.       aButton.removeAttribute("open");
  624.     return true;
  625.   }
  626.   return false;
  627. }
  628.  
  629. // sometimes context popup stay "open", we hide it manually.
  630. function TM_hidePopup () {
  631.    var node = document.popupNode;
  632.    while (node && node.localName != "menubar" && node.localName != "toolbar") {
  633.       if (node.localName == "menupopup" || node.localName == "popup") {
  634.          if (node.hasAttribute("open")) node.removeAttribute("open");
  635.          node.hidePopup();
  636.       }
  637.       node = node.parentNode;
  638.    }
  639. }
  640.  
  641. // return the indexd tab from the list and remove the tab from the list
  642. function getClosedTab(aWhere, aIndex) {
  643.    var ctabs = gBrowser.closedTabs;
  644.    var aTab = null;
  645.    var updateRDF = SessionManager.enableBackup && SessionPref.getBoolPref("save.closedtabs");
  646.    if(aIndex >= 0) {
  647.       if (updateRDF)
  648.          SessionManager.deleteClosedtabAt(ctabs.length - aIndex);
  649.       aTab = ctabs.splice(aIndex, 1)[0];
  650.    } else if (aIndex == -2)
  651.       gBrowser.delayUndoRemoveAllTab();
  652.    else if (aIndex == -1) {
  653.       while(ctabs.length > 0) ctabs.pop();
  654.       if (updateRDF)
  655.          SessionManager.deleteWinClosedtabs(gSessionPath[0] + "/" + gBrowser.windowID);
  656.    }
  657.    if (ctabs.length < 1)
  658.      TMP_ClosedTabs.setButtonDisableState(true);
  659.    return aTab;
  660. }
  661.  
  662. // restore the tab. we only use it if sessionStore is off
  663. function _restoreTab(aWhere, aIndex) {
  664.   var newIndex, aTab = getClosedTab(aWhere, aIndex);
  665.   if (!aTab) return;
  666.   switch (aWhere) {
  667.     case "current":
  668.       var cTab = gBrowser.mCurrentTab;
  669.       newIndex = cTab._tPos;
  670.       cTab.collapsed = true;
  671.       var restoredTab = gBrowser.restoreTab(newIndex, aTab.history, aTab.properties, aTab.scroll);
  672.       if (restoredTab != cTab)
  673.          gBrowser.removeTab(cTab);
  674.       else
  675.          cTab.collapsed = false;
  676.       break;
  677.     case "window":
  678.       var newWindow = window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no");
  679.       newWindow.tabmix_afterTabduplicated = true;
  680.       newWindow.tabmix_duplicatData = {
  681.          scroll: aTab.scroll,
  682.          oldHistory: aTab.history,
  683.          prop: aTab.properties
  684.       }
  685.       break;
  686.     case "tab":
  687.       if (gTabmixPrefs.getBoolPref("extensions.tabmix.openTabNext"))
  688.          newIndex = gBrowser.mCurrentTab._tPos+1;
  689.       else
  690.          newIndex = gBrowser.mTabs.length;
  691.       gBrowser.restoreTab(newIndex, aTab.history, aTab.properties, aTab.scroll);
  692.       break;
  693.     case "original":
  694.       gBrowser.restoreTab(aTab.pos, aTab.history, aTab.properties, aTab.scroll);
  695.   }
  696. }
  697.  
  698. function NW_waitForSessionHistory(event) {
  699.    waitForSessionHistory(20);
  700. }
  701.  
  702. //  wait For sessionHistory in new window
  703. function waitForSessionHistory(attempts) {
  704.    var webNav = gBrowser.webNavigation;
  705.    try{ webNav.sessionHistory; } // Test if sessionHistory exists yet
  706.    catch (err) { // webNav.sessionHistory is not yet available, try again later
  707.       if (attempts) window.setTimeout('waitForSessionHistory(' + --attempts + ')', 50);
  708.       return;
  709.    }
  710.    if ((webNav.sessionHistory == null) && attempts){
  711.       window.setTimeout('waitForSessionHistory(' + --attempts + ')', 50);
  712.       return;
  713.    }
  714.    gBrowser.restoreTab(gBrowser.selectedTab._tPos,
  715.                        window.duplicatData.oldHistory,
  716.                        window.duplicatData.prop,
  717.                        window.duplicatData.scroll);
  718.    delete window.duplicatData;
  719.    if (window.opener && window.opener.needToClose)
  720.       setTimeout(function() {window.opener.closeWindow(true);}, 0);
  721. }
  722.  
  723. function removeTabFromList (event, popup, aType) {
  724.   if (!tabxPrefs.getBoolPref("middleclickDelete"))
  725.     return;
  726.  
  727.   if (event.target.id == "btn_tabslistSorted")
  728.     return;
  729.  
  730.   if (event.button == 1) {
  731.     var aTab = event.originalTarget.tab;
  732.     if (popup.parentNode.id == "tm-tabsList" && (gBrowser.mCurrentTab == aTab || gBrowser.isBlankTab(gBrowser.mCurrentTab))) {
  733.          popup.hidePopup();
  734.          gBrowser.removeTab(aTab, true);
  735.          return;
  736.     }
  737.     gBrowser.removeTab(aTab, true);
  738.     if (gBrowser.mTabs.length > 0) {
  739.       createTabsList(popup, aType);
  740.       var item = popup.parentNode.parentNode;
  741.       if (item.parentNode.id == "btn_tabslist") createTabsList(item, aType);
  742.     }
  743.     else popup.hidePopup();
  744.   }
  745. }
  746.  
  747. // called from tabmix.xml tabs scroll buttons
  748. function _createTabsList (event, side) {
  749.    event.stopPropagation();
  750.    event.preventDefault();
  751.  
  752.    var tablist =  document.getElementById("tabslist");
  753.  
  754.    beforeCommonList(tablist);
  755.    createCommonList(tablist, 2, side);
  756.  
  757.    if (tablist.hasChildNodes())
  758.       tablist.showPopup(event.target, -1, -1, "popup", "bottomleft","topleft");
  759. }
  760.  
  761. // show sort/unsort tabs list popup after click on sorted tab menu
  762. function showTabsListPopup (event) {
  763.    event.stopPropagation();
  764.    setTimeout( function (popup){
  765.       popup.showPopup(popup.parentNode, -1, -1, "popup", "bottomleft", "topleft");
  766.    }, 0, event.target.parentNode);
  767. }
  768.  
  769. function createTabsList (popup, aType) {
  770.   if (isAfterCtrlClick(popup.parentNode))
  771.     return false;
  772.  
  773.   // the context menu isn't visible if the strip is collapsed
  774.   // uncollapsed the stip and collapsed the tabbar instead
  775.   if (popup.id == "btn_tabslist_menu" && !gBrowser.getStripVisibility()) {
  776.     if (!popup.hasAttribute("tabBar_collapsed")) {
  777.       var visibility = gBrowser.mTabContainer.collapsed;
  778.       popup.setAttribute("tabBar_collapsed", visibility);
  779.       if (!visibility)
  780.         gBrowser.mTabContainer.collapsed = true;
  781.     }
  782.     TMP_setStripVisibilityTo(true);
  783.   }
  784.  
  785.   var tabContextMenu = gBrowser.tabContextMenu;
  786.   if (popup.hasAttribute("contextmenu") && popup.getAttribute("contextmenu") != tabContextMenu.id)
  787.     popup.setAttribute("contextmenu", tabContextMenu.id);
  788.  
  789.   if (gTabmixPrefs.getBoolPref("extensions.tabmix.enableScrollSwitch"))
  790.     popup.addEventListener("DOMMouseScroll", TMP_eventListener, true);
  791.  
  792.   beforeCommonList(popup);
  793.   createCommonList(popup, aType);
  794.  
  795.   return true;
  796. }
  797.  
  798. function beforeCommonList(popup) {
  799.   var item = popup.parentNode;
  800.   if (item.id == "btn_tabslist" || item.id == "btn_undoclose")
  801.     item.removeAttribute("tooltiptext");
  802.  
  803.   // clear out the menu popup if we show the popup after middle click
  804.   while (popup.hasChildNodes()) {
  805.     var menuItem = popup.firstChild;
  806.     if (menuItem.id.indexOf("btn_tabslist") != -1)
  807.       break;
  808.     menuItem.removeEventListener("click", TMP_ClosedTabs.checkForMiddleClick, false);
  809.     popup.removeChild(menuItem);
  810.   }
  811.  
  812.   popup.addEventListener("DOMMenuItemActive", updateMenuItemActive, false);
  813.   popup.addEventListener("DOMMenuItemInactive", updateMenuItemInactive, false);
  814. }
  815.  
  816. function createCommonList (popup, aType, side) {
  817.   var tabs;
  818.   var i;
  819.  
  820.   switch(aType) {
  821.     case 1:
  822.       tabs = new Array(gBrowser.mTabs.length);
  823.       for (i = 0; i < gBrowser.mTabs.length; i++)
  824.          tabs[i] = new tabSorting(gBrowser.mTabs[i], i);
  825.       tabs = tabs.sort();
  826.       for (i = 0; i < tabs.length; i++)
  827.          createMenuItems(popup, tabs[i].Tab, tabs[i].Index, aType);
  828.       break;
  829.     case 2:
  830.       var rtl = window.getComputedStyle(gBrowser, null).direction == "rtl" && gTabmixPrefs.getIntPref("extensions.tabmix.tabBarMode") != 2;
  831.       tabs = gBrowser.mTabs;
  832.       for (i = 0; i < tabs.length; i++) {
  833.          let index = tabs[i]._tPos;
  834.          if (side && side == (rtl ? "right" : "left") && !tabs[i].collapsed)
  835.             continue;
  836.          else if (side && side == (rtl ? "left" : "right") &&
  837.                (tabs[i].collapsed || gBrowser.mTabContainer.isTabVisible(index)))
  838.             continue;
  839.          createMenuItems(popup, tabs[i], index, aType);
  840.       }
  841.       break;
  842.     case 3:
  843.       for (i = TMP_LastTab.TabHistory.length - 1; i >= 0; i--)
  844.          createMenuItems(popup, TMP_LastTab.TabHistory[i], i, aType);
  845.       break;
  846.   }
  847. }
  848.  
  849. function createMenuItems(popup, tab, value, aType) {
  850.   var count, mi = document.createElement("menuitem");
  851.   mi.setAttribute("class", "menuitem-iconic bookmark-item alltabs-item");
  852.   mi.setAttribute("statustext", gBrowser.getBrowserForTab(tab).currentURI.spec);
  853.   mi.setAttribute("tooltiptext", tab.label);
  854.   count = aType != 3 ? (value + 1) + (value < 9 ? " : " : ": ") : "";
  855.   mi.setAttribute("count", count);
  856.   mi.setAttribute("label", count + tab.label);
  857.   mi.setAttribute("crop", tab.getAttribute("crop"));
  858.   mi.setAttribute("image", tab.getAttribute("image"));
  859.  
  860.   if (tab.hasAttribute("busy"))
  861.     mi.setAttribute("busy", tab.getAttribute("busy"));
  862.   if (tab.selected)
  863.      mi.setAttribute("selected", "true");
  864.  
  865.   mi.value = value;
  866.   tab.mCorrespondingMenuitem = mi;
  867.   tab.addEventListener("DOMAttrModified", TMP_tabOnAttrModified, false);
  868.   tab.addEventListener("TabClose", TMP_tabOnTabClose, false);
  869.   mi.tab = tab;
  870.  
  871.   if (popup.id == "btn_tabslist_menu")
  872.     popup.insertBefore(mi, document.getElementById("btn_tabslist_sep"));
  873.   else
  874.     popup.appendChild(mi);
  875. }
  876.  
  877. function TMP_tabOnAttrModified(aEvent) {
  878.   var menuItem = aEvent.target.mCorrespondingMenuitem;
  879.   if (menuItem) {
  880.     var attrName = aEvent.attrName;
  881.     var count = "";
  882.     switch (attrName) {
  883.       case "label":
  884.         count = menuItem.getAttribute("count");
  885.       case "crop":
  886.       case "busy":
  887.       case "image":
  888.       case "selected":
  889.         if (aEvent.attrChange == aEvent.REMOVAL)
  890.           menuItem.removeAttribute(attrName);
  891.         else
  892.           menuItem.setAttribute(attrName, count + aEvent.newValue);
  893.     }
  894.   }
  895. }
  896.  
  897. function TMP_tabOnTabClose(aEvent) {
  898.    var menuItem = aEvent.target.mCorrespondingMenuitem;
  899.    if (menuItem && menuItem.parentNode)
  900.       menuItem.parentNode.removeChild(menuItem);
  901. }
  902.  
  903. function TMP_TabsListOncommand(event) {
  904.    TMP_tabSelectedFromList(event.originalTarget.tab);
  905. }
  906.  
  907. function TMP_tabSelectedFromList(aTab) {
  908.    if (gBrowser.selectedTab == aTab)
  909.       gBrowser.mTabContainer.ensureTabIsVisible(gBrowser.mTabContainer.selectedIndex);
  910.    else
  911.       // if we select another tab _handleTabSelect will call ensureTabIsVisible
  912.       gBrowser.selectedTab = aTab;
  913. }
  914.  
  915. var gBackupLabel = "";
  916. function hideCommonList(popup) {
  917.  
  918.   // restore the strip collapsed status
  919.   if (popup.id == "btn_tabslist_menu" && popup.hasAttribute("tabBar_collapsed")) {
  920.     TMP_setStripVisibilityTo(false);
  921.     var visibility = gBrowser.mTabContainer.collapsed;
  922.     if (popup.getAttribute("tabBar_collapsed") == "false")
  923.       gBrowser.mTabContainer.collapsed = false;
  924.     popup.removeAttribute("tabBar_collapsed");
  925.   }
  926.  
  927.   // clear out the menu popup and remove the listeners
  928.   while (popup.hasChildNodes()) {
  929.     var menuItem = popup.firstChild;
  930.     if (menuItem.id.indexOf("btn_tabslist") != -1)
  931.       break;
  932.     if ("tab" in menuItem) {
  933.       menuItem.tab.removeEventListener("DOMAttrModified", TMP_tabOnAttrModified, false);
  934.       menuItem.tab.removeEventListener("TabClose", TMP_tabOnTabClose, false);
  935.       menuItem.tab.mCorrespondingMenuitem = null;
  936.     }
  937.     popup.removeChild(menuItem);
  938.   }
  939.  
  940.   var item = popup.parentNode;
  941.   if (item.id == "btn_tabslist" || item.id == "btn_undoclose")
  942.     item.setAttribute('tooltiptext', item.getAttribute('_tooltiptext'));
  943.  
  944.   popup.removeEventListener("DOMMenuItemActive", updateMenuItemActive, false);
  945.   popup.removeEventListener("DOMMenuItemInactive", updateMenuItemInactive, false);
  946.   popup.removeEventListener("DOMMouseScroll", TMP_eventListener, true);
  947.  
  948.   gBackupLabel = "";
  949. }
  950.  
  951. function updateMenuItemActive(event, tab) {
  952.    var statusTextFld = document.getElementById("statusbar-display");
  953.    if (gBackupLabel=="") gBackupLabel = statusTextFld.label;
  954.    if (!tab) tab = event.target;
  955.    updateStatusText(tab.getAttribute("statustext"));
  956. }
  957.  
  958. function updateMenuItemInactive(event) {
  959.    updateStatusText("");
  960. }
  961.  
  962. function updateStatusText(itemText) {
  963.    var statusTextFld = document.getElementById("statusbar-display");
  964.    var newText = itemText ? itemText : gBackupLabel;
  965.    if (newText != statusTextFld.label)
  966.       statusTextFld.label = newText;
  967. }
  968.  
  969. function tabSorting(tab, index) {
  970.    this.Tab = tab;
  971.    this.Index = index;
  972. }
  973.  
  974. tabSorting.prototype.toString = function() { return this.Tab.label.toLowerCase(); }
  975.